﻿namespace MSU_WebServices
{
    using System;
    using MSU_Broker;
    using System.Web.Services.Protocols;
    using System.Xml;
using System.Collections.Generic;
    public class MSU_ExceptionPack
    {
        static MSU_ExceptionPack()
        { 
        }

        public enum FaultCode
        {
            Client = 0,
            Server = 1
        }

        public static SoapException PackSOAP(string uri, string webServiceNamespace, FaultCode code, Exception e, List<MSU_Error> errorsToScreen)
        {
            XmlQualifiedName faultCodeLocation = null;
            string message = "";
            string stackTrace = "";
            MSU_Error errorType = MSU_Error.UNEXPECTED_ERROR;
            bool haveInnerException = false;

            //Identify the location of the FaultCode
            switch (code)
            {
                case FaultCode.Client:
                    faultCodeLocation = SoapException.ClientFaultCode;
                    break;
                case FaultCode.Server:
                    faultCodeLocation = SoapException.ServerFaultCode;
                    break;
            }

            if (e is MSU_Exception)
            {
                MSU_Exception MSU_e = (MSU_Exception)e;
                errorType = MSU_e.ErrorType;
                haveInnerException = MSU_e.InnerException != null;
            }
            message = e.Message;
            stackTrace = e.StackTrace;


            XmlDocument xmlDoc = new XmlDocument();

            //Create the Detail node
            XmlNode rootNode = xmlDoc.CreateNode(XmlNodeType.Element, SoapException.DetailElementName.Name, SoapException.DetailElementName.Namespace);

            //Build specific details for the SoapException

            //Add first child of detail XML element.
            XmlNode errorNode = xmlDoc.CreateNode(XmlNodeType.Element, "Error", webServiceNamespace);

            XmlNode errorTypeNumberNode = xmlDoc.CreateNode(XmlNodeType.Element, "ErrorTypeNumber", webServiceNamespace);
            XmlNode errorMessageNode = xmlDoc.CreateNode(XmlNodeType.Element, "Message", webServiceNamespace);
            XmlNode errorStackTraceNode = xmlDoc.CreateNode(XmlNodeType.Element, "StackTrace", webServiceNamespace);
            XmlNode innerErrorNode = xmlDoc.CreateNode(XmlNodeType.Element, "InnerError", webServiceNamespace);
            XmlNode errorOnScreen = xmlDoc.CreateNode(XmlNodeType.Element, "OnScreen", webServiceNamespace);

            errorOnScreen.InnerText = (errorsToScreen.Contains(errorType)).ToString();
            errorTypeNumberNode.InnerText = ((int)errorType).ToString();
            errorMessageNode.InnerText = message;
            errorStackTraceNode.InnerText = stackTrace;

            if (haveInnerException)
            {

                Exception currentInnerException = e.InnerException;
                XmlNode currentErrorNode = innerErrorNode;

                XmlNode currentErrorOnScreen;
                XmlNode currentErrorTypeNumberNode;
                XmlNode currentErrorMessageNode;
                XmlNode currentErrorStackTraceNode;
                XmlNode currentInnerErrorNode;

                while (currentInnerException != null)
                {
                    currentErrorTypeNumberNode = xmlDoc.CreateNode(XmlNodeType.Element, "ErrorTypeNumber", webServiceNamespace);
                    currentErrorMessageNode = xmlDoc.CreateNode(XmlNodeType.Element, "Message", webServiceNamespace);
                    currentErrorStackTraceNode = xmlDoc.CreateNode(XmlNodeType.Element, "StackTrace", webServiceNamespace);
                    currentInnerErrorNode = xmlDoc.CreateNode(XmlNodeType.Element, "InnerError", webServiceNamespace);
                    currentErrorOnScreen = xmlDoc.CreateNode(XmlNodeType.Element, "OnScreen", webServiceNamespace);
                    
                    if (currentInnerException is MSU_Exception)
                    {
                        currentErrorOnScreen.InnerText = (errorsToScreen.Contains(((MSU_Exception)currentInnerException).ErrorType)).ToString();
                        currentErrorTypeNumberNode.InnerText = ((int)((MSU_Exception)currentInnerException).ErrorType).ToString();
                        currentErrorMessageNode.InnerText = currentInnerException.Message;
                        currentErrorStackTraceNode.InnerText = currentInnerException.StackTrace;

                        currentErrorNode.AppendChild(currentErrorTypeNumberNode);
                        currentErrorNode.AppendChild(currentErrorMessageNode);
                        currentErrorNode.AppendChild(currentErrorStackTraceNode);
                        currentErrorNode.AppendChild(currentInnerErrorNode);
                        currentErrorNode.AppendChild(currentErrorOnScreen);

                        currentErrorNode = currentInnerErrorNode;
                        currentInnerException = currentInnerException.InnerException;
                    }
                    else
                    {
                        currentErrorOnScreen.InnerText = false.ToString();
                        currentErrorMessageNode.InnerText = currentInnerException.Message;
                        currentErrorStackTraceNode.InnerText = currentInnerException.StackTrace;
                        currentErrorTypeNumberNode.InnerText = ((int)MSU_Error.UNEXPECTED_ERROR).ToString();
                        currentInnerException = null;
                    }
                }
            }

            //Append the Error child element nodes to the root detail node.
            errorNode.AppendChild(errorTypeNumberNode);
            errorNode.AppendChild(errorMessageNode);
            errorNode.AppendChild(errorStackTraceNode);
            errorNode.AppendChild(innerErrorNode);

            //Append the Detail node to the root node
            rootNode.AppendChild(errorNode);

            return new SoapException(message, faultCodeLocation, uri, rootNode);
        }
    }
}
